package org.blogwu.learn.threadLearn.使用unsafe实现原子性;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * 自己使用Unsafe来保证原子性
 * https://www.cnblogs.com/throwable/p/9139947.html
 *
 * @author hyf
 * @date 2019-05-26
 **/
public class Main {

    public static void main(String[] args) throws InterruptedException, NoSuchFieldException {
        AtomicInt atomicInt = new AtomicInt();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100000; i++) {
                    for (; ; ) {
                        int current = atomicInt.getA();
                        int next = current + 1;
                        if (atomicInt.compleAndSet(current, next)) {
                            break;
                        }
                    }
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100000; i++) {
                    for (; ; ) {
                        int current = atomicInt.getA();
                        int next = current + 1;
                        if (atomicInt.compleAndSet(current, next)) {
                            break;
                        }
                    }
                }
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("i:" + atomicInt.getA());
    }
}

class AtomicInt {
    Unsafe unsafe = null;

    volatile int a = 0;
    long valueOffset;

    {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe"); //获得名为 theUnsafe 的属性 即使为私有 同样获得
            f.setAccessible(true);
            unsafe = (Unsafe) f.get(null);  //如果为静态属性 则get 参数为null
            Field field = AtomicInt.class.getDeclaredField("a");
            valueOffset = unsafe.objectFieldOffset(field);
            System.out.println("offset：" + valueOffset);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public int getA() {
        return this.a;
    }

    public boolean compleAndSet(int current, int next) {
        return unsafe.compareAndSwapInt(this, valueOffset, current, next);
    }
}
